#include "fs/fat32.h"
#include "fs/file.h"
#include "lock.h"

#include "mmu.h"
#include "mmulayout.h"
#include "riscv.h"
#include "stddef.h"
#include "stdio.h"
#include "string.h"
#include "trap.h"
#include "type.h"

#include "proc.h"


#include "dbg.h"

proc_t proc[NPROC];

extern void contentSwitch(context_t *, context_t *);

void yield(void){
    __DEBUG_FUNC_START;
    proc_t *p = getCurrentProc();
    spinlock_acquire(&p->lk);
    p->state = READY;
    sched();

}

void sched(void)
{
    proc_t *p = getCurrentProc();
    contentSwitch(&p->context, &getCurrentCPU()->context);
}

void scheduler(void)
{
    proc_t *p;
    extern pageTable_t kernel_pagetable;
    while(1)
    {
        intr_on();
        for(p = proc; p < &proc[NPROC]; p++)
        {
            spinlock_acquire(&p->lk);
            if(p->state == READY)
            {
                p->state = RUNNING;
                getCurrentCPU()->current_p = p;
                p->tms.entry_kernel = r_time();
                w_satp(PAGE_TABLE_SHIFT(p->kpageTable));
                sefenve_vma();
                contentSwitch(&(getCurrentCPU()->context), &(p->context));
                if(!spinlock_isHold(&p->lk))
                {
                    //TODO
                }
                spinlock_release(&p->lk);
                if(getCurrentCPU()->current_p != p)
                {
                    //TODO
                }
                w_satp(PAGE_TABLE_SHIFT(kernel_pagetable));
                sfenve_vma();
                getCurrentCPU()->current_p = NULL;
            }
            spinlock_release(&p->lk);
        }
    }
}